package top.vains.controller;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.vains.entity.Result;
import top.vains.enumeration.ResultEnum;
import top.vains.exception.CustomerException;
import top.vains.freemarker.Field;
import top.vains.freemarker.MarkerConfig;
import top.vains.freemarker.TemplateFile;
import top.vains.service.IFilesService;
import top.vains.util.ResultUtils;
import top.vains.util.TemplateUtils;
import top.vains.util.VideoUtils;

import javax.sql.DataSource;
import java.io.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * 测试接口
 *
 * @author vains
 * @version 1.0
 * @date 2020/3/18 13:15
 **/
@Slf4j
@RestController
@RequestMapping("/test")
@Api(tags = "测试接口，可以在本接口中做测试")
public class TestController {

    private final DataSource dataSource;

    private final Configuration configuration;

    private final IFilesService filesService;

    @Autowired
    public TestController(DataSource dataSource, Configuration configuration, IFilesService filesService) {
        this.dataSource = dataSource;
        this.configuration = configuration;
        this.filesService = filesService;
    }

    @GetMapping("/testDataSource")
    @ApiOperation(value = "测试获取当前连接的数据库中所有的表", notes = "所有文件会通过该接口进行上传")
    public Result testDataSource() {
        List<String> names;
        // try-with-resources的方式获取连接
        try (Connection connection = dataSource.getConnection()) {
            // 获取数据库名称
            String catalog = connection.getCatalog();
            // 获取当前数据库中所有的表
            ResultSet tables = connection.getMetaData().getTables(catalog, "%", "%", new String[]{"TABLE"});
            names = new ArrayList<>();
            // 遍历所有的表，获取表名
            while (tables.next()) {
                names.add(tables.getString("TABLE_NAME"));
            }
        } catch (SQLException e) {
            throw new CustomerException("获取数据库信息失败！");
        }
        //响应
        return ResultUtils.success(ResultEnum.SUCCESS.getMessage(), names);
    }

    @GetMapping("/testUnderLine/{line}/{upperCase}")
    @ApiOperation(value = "测试下划线转驼峰", notes = "首字母大小写")
    public Result testUnderLine(@PathVariable("line") String line, @PathVariable("upperCase") Boolean upperCase) {
        String camel = TemplateUtils.underLineCame(line, upperCase);
        return ResultUtils.success(camel);
    }

    @GetMapping("/preViewEntity/{tableName}")
    @ApiOperation(value = "测试生成文件预览", notes = "预览文件")
    public Result preViewEntity(@PathVariable("tableName") String tableName) {
        try (Connection connection = dataSource.getConnection()) {
            List<Field> fields = new ArrayList<>();
            MarkerConfig config = new MarkerConfig();
            config.setAuthor("vains");
            config.setUseLombok(true);
            config.setUseSwagger2(true);
            config.setBasePackage("top.vains.test");
            config.setOutputDir(System.getProperty("user.dir")+ "/src/main/java");
            // 获取数据库名称
            String catalog = connection.getCatalog();
            // 获取当前数据库中所有的表
            DatabaseMetaData metaData = connection.getMetaData();
            ResultSet columns = metaData.getColumns(catalog, "%", tableName, "%");
            String className = TemplateUtils.underLineCame(tableName, true);
            ResultSet primaryKeys = metaData.getPrimaryKeys(catalog, null, tableName);
            Set<String> imports = new HashSet<>();
            while (columns.next()) {
                Field field = new Field();
                String fieldName = columns.getString("COLUMN_NAME");
                field.setFieldName(TemplateUtils.underLineCame(fieldName, false));
                int dataType = Integer.parseInt(columns.getString("DATA_TYPE"));
                String sqlToJava = TemplateUtils.sqlToJava(dataType);
                String[] split = sqlToJava.split("\\.");
                if (split.length > 1) {
                    imports.add(sqlToJava);
                    sqlToJava = split[split.length - 1];
                }
                field.setDataType(sqlToJava);
                field.setHaveUnderLine(!TemplateUtils.underLineCame(fieldName, false).equalsIgnoreCase(fieldName));
                field.setRemarks(columns.getString("REMARKS"));
                fields.add(field);
            }
            TemplateFile file = new TemplateFile();
            file.setClassName(className);
            List<String> keys = new ArrayList<>();
            // 取出所有主键
            while (primaryKeys.next()) {
                String fieldName = primaryKeys.getString("COLUMN_NAME");
                keys.add(TemplateUtils.underLineCame(fieldName, false));
            }
            // 找到主键
            for (Field field : fields) {
                if (keys.contains(field.getFieldName())) {
                    field.setPrimaryKey(true);
                }
            }
            file.setFields(fields);
            Map<String, Object> map = new HashMap<>();
            file.setImports(imports);
            map.put("config", config);
            map.put("file", file);
            configuration.setDirectoryForTemplateLoading(new File(System.getProperty("user.dir") + "/src/main/resources/templates/generator/"));
            configuration.setDefaultEncoding("UTF-8");
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            Template template = configuration.getTemplate("entity.ftl");
            String[] split = config.getBasePackage().split("\\.");
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : split) {
                stringBuilder.append("/").append(s);
            }
            File dir = new File(config.getOutputDir() + stringBuilder.toString());
            if (!dir.exists()) {
                boolean mkdirs = dir.mkdirs();
                if (!mkdirs) {
                    log.error("文件夹创建失败");
                    throw new CustomerException("文件获取失败！");
                }
            }
            String templateIntoString = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            return ResultUtils.success(ResultEnum.SUCCESS.getMessage(), templateIntoString);
        } catch (Exception e) {
            log.error("文件生成失败，原因：", e);
        }
        return ResultUtils.error("文件生成失败");
    }


    @GetMapping("/testCount")
    @ApiOperation(value = "测试空接口请求次数", notes = "需要携带token")
    public Result getFilesByType() {
        return ResultUtils.success("查询成功！");
    }

    @GetMapping("/getFileParentPath")
    @ApiOperation(value = "测试获取文件父路径", notes = "需要携带token")
    public Result getFileParentPath(Integer id) {
        String parentPath = VideoUtils.getParentPath(id, filesService, null);
        return ResultUtils.success("查询成功！", parentPath);
    }

}
